package jwdt.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import jwdt.common.Constant;
import jwdt.vo.DevToolsVo;
import jwdt.vo.InitProDataSourceVo;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ProjectPropertiesUtils {
	
	/**
	 * 解析文件'.project'以获取Project Name, 此种方法要求'.project'文件根节点的第一个name子节点即是Project
	 */
	private static final String PROJECT_NAME_FILE = "/.project";
	/**
	 * 解析文件'.classpath'以获取javaSourcesPath以及outputPath.
	 */
	private static final String CLASS_PATH_FILE = "/.classpath";
	/**
	 * 解析文件'.settings/.jsdtscope'以获取webappPath.
	 */
	private static final String WEBAPP_PATH_FILE = "/.settings/.jsdtscope";
	/**
	 * 解析文件'.settings/org.eclipse.wst.common.project.facet.core.xml'以获取moduleVersion，javaVersion.
	 */
	private static final String VERSION_PATH_FILE = "/.settings/org.eclipse.wst.common.project.facet.core.xml";
	/**
	 * 解析文件'.settings/.jwdt.initproframework'以获取framework，datasource.
	 */
	private static final String JWDT_INITPROFRAMEWORK_PATH_FILE = "/.settings/.jwdt.initproframework";
	/**
	 * 解析文件'.settings/.jwdt.devtools'以获取devtoolsInfo.
	 */
	private static final String JWDT_DEVTOOLS_PATH_FILE = "/.settings/.jwdt.devtools";
	
	//Eclipse的Project的绝对路径地址.
	private String projectPath;
	//Project是否是Dynamic Web Project.
	private boolean isJavaDynamicWebProject = false;
	//Eclipse的Dynamic Web Project的项目名称.
	private String projectName;
	//Eclipse的Dynamic Web Project的Java Sources path.
	private String[] javaSourcesPath;
	//Eclipse的Dynamic Web Project的Output classes path.
	private String outputPath;
	//Eclipse的Dynamic Web Project的Webapp path.
	private String webappPath;
	//Eclipse的Dynamic Web Project的Dynamic Web module version.
	private String moduleVersion;
	//Eclipse的Dynamic Web Project的java version.
	private String javaVersion;
	//是否已使用JWDT初始化
	private boolean isInitProFrameWork = false;
	//架构信息
	private Map<String,String> frameWorks = new HashMap<String,String>();
	//数据源信息
	private Map<String,InitProDataSourceVo> initProDataSourceVoMap = new HashMap<String,InitProDataSourceVo>();
	//devtoolsInfo
	private DevToolsVo devtoolsInfo = new DevToolsVo();
	
	public ProjectPropertiesUtils(String projectPath) throws Exception{
		this.projectPath=projectPath;
		this.parseProject();
	}
	
	/**
	 * 解析Java Dynamic Web Project(2.4/2.5)的属性文件获得Project相关属性.
	 */
	private void parseProject() throws Exception{
		if (!new File(this.projectPath + PROJECT_NAME_FILE).exists() || 
				!new File(this.projectPath + CLASS_PATH_FILE).exists() || 
				!new File(this.projectPath + WEBAPP_PATH_FILE).exists() || 
				!new File(this.projectPath + VERSION_PATH_FILE).exists()) {
			throw new IllegalArgumentException("This is not a valid Java Dynamic Web Project(2.4/2.5).");
		}
		
		//先获取moduleVersion和javaVersion，如果moduleVersion不存在，则不被认为是Dynamic Web Project
		this.parseVersions();
		if(this.javaVersion != null && this.moduleVersion != null && (this.moduleVersion.equals("2.4") || this.moduleVersion.equals("2.5"))){
			//解析文件'.settings/.jsdtscope'以获取webappPath.
			this.parseWebappPath();
			//解析文件'.classpath'以获取javaSourcesPath以及outputPath.			
			this.parseJavaSourcesAndOutputPath();
			//解析文件'.project'以获取Project Name, 此种方法要求'.project'文件根节点的第一个name子节点即是Project
			this.parseProjectName();
			//解析文件'.settings/.jwdt'以获取framework，datasource.
			this.parseJWDT();
			
			return;
		}
		throw new IllegalArgumentException("This is not a valid Java Dynamic Web Project(2.4/2.5).");
	}

	/**
	 * 解析文件'.settings/org.eclipse.wst.common.project.facet.core.xml'以获取moduleVersion，javaVersion.
	 * @throws DocumentException 
	 */
	private void parseVersions() throws DocumentException{
		String xmlPath = this.projectPath + VERSION_PATH_FILE;
		
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File(xmlPath));

		Element root = document.getRootElement();
		List<Element> installeds = root.elements("installed");
		for (Element e : installeds) {
			if (e.attributeValue("facet").equals("jst.web")) {
				this.moduleVersion = e.attributeValue("version");

			}
			if (e.attributeValue("facet").equals("java")) {
				this.javaVersion = e.attributeValue("version");
			}
		}
		
		if(this.moduleVersion != null && this.javaVersion != null){
			this.isJavaDynamicWebProject = true;
		}
	}
	
	/**
	 * 解析文件'.settings/.jsdtscope'以获取webappPath.
	 * @throws DocumentException 
	 */
	private void parseWebappPath() throws DocumentException{
		String xmlPath = this.projectPath + WEBAPP_PATH_FILE;
		
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File(xmlPath));
				
		Element root = document.getRootElement();
		List<Element> installeds = root.elements("classpathentry");
		for(Element e : installeds){				
			if(e.attributeValue("kind").equals("src")){
				this.webappPath = e.attributeValue("path");
			}				
		}
	}
	
	/**
	 * 解析文件'.classpath'以获取javaSourcesPath以及outputPath.
	 */
	private void  parseJavaSourcesAndOutputPath() throws DocumentException{
		String xmlPath = this.projectPath + CLASS_PATH_FILE;
		
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File(xmlPath));
		
		Element root = document.getRootElement();
		List<Element> installeds = root.elements("classpathentry");
		List<String> allSrc = new ArrayList<String>();
		for(Element e : installeds){				
			if(e.attributeValue("kind").equals("src")){
				allSrc.add(e.attributeValue("path"));
			}
			if(e.attributeValue("kind").equals("output")){
				this.outputPath = e.attributeValue("path");
			}
		}
		this.javaSourcesPath = new String[allSrc.size()];
		for (int i = 0; i < this.javaSourcesPath.length; i++) {
			this.javaSourcesPath[i] = allSrc.get(i);
		}
	}
	
	/**
	 * 解析文件'.project'以获取Project Name, 此种方法要求'.project'文件根节点的第一个name子节点即是Project
	 */
	private void  parseProjectName() throws DocumentException{
		String xmlPath = this.projectPath + PROJECT_NAME_FILE;
		
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File(xmlPath));
		
		Element root = document.getRootElement();
		Element name = root.element("name");
		this.projectName = name.getStringValue();
	}
	
	/**
	 * 解析文件'.settings/.jwdt.*'以获取framework，datasource，devtoolsInfo.
	 */
	private void  parseJWDT() throws Exception{
		/*
		 * 获取framework，datasource.
		 */
		parseJWDTinitproframework();
		/*
		 * 获取devtoolsInfo
		 */
		parseJWDTdevtools();
	}

	private void parseJWDTdevtools() throws IOException {
		String filePath = this.projectPath + JWDT_DEVTOOLS_PATH_FILE;
		
		if (!new File(filePath).exists()) {
			return;
		}
		
		Properties prop = new Properties();

		InputStream fis = new FileInputStream(filePath);
		prop.load(fis);

		InitProDataSourceVo initProDataSourceVo = new InitProDataSourceVo();
		initProDataSourceVo.setDataSourceName(prop.getProperty("name") == null ? "" : prop.getProperty("name"));
		initProDataSourceVo.setDataBaseType(prop.getProperty("database"));
		initProDataSourceVo.setDataSourceType(prop.getProperty("type"));
		if (Constant.DATASOURCE_TYPE_JDBC.equals(initProDataSourceVo.getDataSourceType())) {
			initProDataSourceVo.setDriverClass(prop.getProperty("driver"));
			initProDataSourceVo.setDataBaseUrl(prop.getProperty("url"));
			initProDataSourceVo.setUserName(prop.getProperty("username"));
			initProDataSourceVo.setPassWord(prop.getProperty("password"));
		}
		if (Constant.DATASOURCE_TYPE_JNDI.equals(initProDataSourceVo.getDataSourceType())) {
			initProDataSourceVo.setJndiName(prop.getProperty("jndi"));
		}
		initProDataSourceVo.setDefault(Boolean.valueOf(prop.getProperty("isdefault")));
		this.devtoolsInfo.setInitProDataSourceVo(initProDataSourceVo);
		this.devtoolsInfo.setJavaSourcesPath(prop.getProperty("javasources"));
		this.devtoolsInfo.setPackageText(prop.getProperty("package"));	
		this.devtoolsInfo.setTablePattern(prop.getProperty("tablepattern"));
	}
	
	private void parseJWDTinitproframework() throws DocumentException{
		String xmlPath = this.projectPath + JWDT_INITPROFRAMEWORK_PATH_FILE;
		
		if(!new File(xmlPath).exists()){
			return;
		}
		
		//isInitProFrameWork
		this.isInitProFrameWork = true;
			
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File(xmlPath));
		
		Element root = document.getRootElement();
		//framework
		Element framework = root.element("framework");
		this.frameWorks.clear();
		this.frameWorks.put(Constant.MVC, framework.attributeValue("mvc"));
		this.frameWorks.put(Constant.IOC, framework.attributeValue("ioc"));
		this.frameWorks.put(Constant.ORM, framework.attributeValue("orm"));
		this.frameWorks.put(Constant.PAGE, framework.attributeValue("page"));
		//datasource
		List<Element> datasources = root.elements("datasource");
		this.initProDataSourceVoMap.clear();
		for (Element element: datasources) {
			InitProDataSourceVo initProDataSourceVo = new InitProDataSourceVo();
			initProDataSourceVo.setDataSourceName(element.attributeValue("name"));
			initProDataSourceVo.setDataBaseType(element.attributeValue("database"));
			initProDataSourceVo.setDataSourceType(element.attributeValue("type"));
			if(Constant.DATASOURCE_TYPE_JDBC.equals(element.attributeValue("type"))){
				initProDataSourceVo.setDriverClass(element.attributeValue("driver"));
				initProDataSourceVo.setDataBaseUrl(element.attributeValue("url"));
				initProDataSourceVo.setUserName(element.attributeValue("username"));
				initProDataSourceVo.setPassWord(element.attributeValue("password"));
			}
			if(Constant.DATASOURCE_TYPE_JNDI.equals(element.attributeValue("type"))){
				initProDataSourceVo.setJndiName(element.attributeValue("jndi"));
			}
			initProDataSourceVo.setDefault(Boolean.valueOf(element.attributeValue("isdefault")));
			this.initProDataSourceVoMap.put(element.attributeValue("name"), initProDataSourceVo);
		}
	}
	
	public String getProjectPath() {
		return projectPath;
	}
	
	public String getProjectParentPath() {
		if(this.projectPath == null){
			return null;
		}
		return this.projectPath.substring(0, this.projectPath.lastIndexOf("/"));
	}
	
	public boolean isJavaDynamicWebProject() {
		return isJavaDynamicWebProject;
	}

	public String getProjectName() {
		return projectName;
	}

	public String[] getJavaSourcesPath() {
		return javaSourcesPath;
	}

	public String getOutputPath() {
		return outputPath;
	}

	public String getWebappPath() {
		return webappPath;
	}

	public String getModuleVersion() {
		return moduleVersion;
	}

	public String getJavaVersion() {
		return javaVersion;
	}

	public boolean isInitProFrameWork() {
		return isInitProFrameWork;
	}

	public Map<String, String> getFrameWorks() {
		return frameWorks;
	}

	public Map<String, InitProDataSourceVo> getInitProDataSourceVoMap() {
		return initProDataSourceVoMap;
	}

	public DevToolsVo getDevtoolsInfo() {
		return devtoolsInfo;
	}
}
